import qs from 'qs'
import 'vant/es/toast/style'
import { baseDomain } from '../apis'
import { navigation2Login } from './login'
import { AUTHORIZATION_TOKEN } from '../constant'
import { closeToast } from 'vant'
import { ApiType, configDataType } from '../types/api'
import { localStorageMethods } from '../common/storage'
import { showError, showSuccess } from '../common/notify'
import axios, { AxiosProgressEvent, AxiosResponse } from 'axios'
import { isNotEmpty } from '@/framework/utils/common'
import { showToast } from '@/framework/utils/notice'

export const baseURL = (import.meta as any).env.VITE_baseURL + baseDomain + '/web'
const clientType = isNotEmpty((import.meta as any).env.VITE_clientType)
  ? (import.meta as any).env.VITE_clientType
  : '0'

const axiosInstance = axios.create({})

axiosInstance.interceptors.request.use(
  (config) => {
    const { data, showLoading } = config.data as configDataType
    if (showLoading) {
      showToast()
    }
    config.data = data
    const token = localStorageMethods.getLocalStorage(AUTHORIZATION_TOKEN)
    if (token)
      config.headers['Authorization'] = 'Bearer ' + localStorageMethods.getLocalStorage(AUTHORIZATION_TOKEN)
    return config
  },
  (err) => {
    console.log(err)
    closeToast()
    return showError('请求超时，请检查网络设置!')
  }
)

axiosInstance.interceptors.response.use(
  (resp) => {
    closeToast()
    if (resp.data.status?.code === 401) {
      showError('登录已过期请重新登录')
      navigation2Login()
    }
    return Promise.resolve(resp)
  },
  (err) => {
    closeToast()
    if (err.response.status === 504 || err.response.status === 404) {
      showError('服务器被吃了⊙﹏⊙∥')
    } else if (err.response.status === 403) {
      showError('权限不足,请联系管理员!')
    } else if (err.response.status === 500) {
      showError('系统错误,联系管理员!')
    } else if (err.response.status === 502) {
      showError('服务器走神了,请稍等!')
    } else {
      console.log(err)
    }
    throw new Error(err)
  }
)

// apiType method/url/version
// params url的参数
// data 请求体的数据
// showErr 是否显示操作成功提示信息
// showLoading 是否需要在等待期间显示转菊花
// showErr 是否显示错误提示信息
export const request = (
  apiType: ApiType,
  params: object = {},
  body: object = {},
  needShowSuccess = false,
  needShowLoading = true,
  showErr = true
) => {
  const urlParams = qs.stringify(params, { arrayFormat: 'repeat' })
  return axiosInstance({
    baseURL,
    method: apiType.method,
    url: apiType.url + (urlParams && '?' + urlParams),
    data: {
      data: body,
      showLoading: needShowLoading
    },
    params: null,
    headers: {
      'Content-Type': 'application/json',
      'api-version': apiType.version,
      'client-type': clientType
    }
  }).then(
    (response) => {
      const {
        data: { status, payload }
      } = response
      if (isNotEmpty(response.data)) {
        if (status?.code !== 200 && status?.code !== 0) {
          if (status?.msg) {
            if (showErr) {
              showError(payload.errMsg)
              throw new Error(status.msg)
            } else {
              throw new Error(status.msg)
            }
          }
        } else if (needShowSuccess) {
          const message = status.details
          message && showSuccess(message)
        }
      }
      return { status, payload, response }
    },
    (err) => {
      throw new Error(err)
    }
  )
}

export const get = (
  apiType: ApiType,
  params: object = {},
  data: object = {},
  showSuccess = false,
  showLoading = true,
  showErr = true
) => request(apiType, params, data, showSuccess, showLoading, showErr)

export const post = (
  apiType: ApiType,
  params: object = {},
  data: object = {},
  showSuccess = true,
  showLoading = true,
  showErr = true
) => request(apiType, params, data, showSuccess, showLoading, showErr)

export function download(apiType: ApiType, fileName: string, params: object, body: object) {
  showSuccess('开始下载……')
  return axiosInstance({
    baseURL,
    method: apiType.method,
    url: apiType.url + '?' + qs.stringify(params, { arrayFormat: 'repeat' }),
    data: { data: body },
    params: null,
    headers: {
      'Content-Type': 'application/json',
      'api-version': apiType.version,
      'client-type': clientType
    },
    responseType: 'blob'
  }).then(
    (resp) => {
      _download(resp, fileName)
      return {
        status: resp.data.status,
        payload: resp.data.payload,
        response: resp
      }
    },
    (err) => {
      showError('下载失败，请检查网络后重试，或更换设备！')
      console.log(err)
      throw new Error(err)
    }
  )
}

export function upload(
  apiType: ApiType,
  params: object,
  body: object,
  onUploadProgress: (progressEvent: AxiosProgressEvent) => void
) {
  return axiosInstance({
    baseURL,
    method: apiType.method,
    url: apiType.url + '?' + qs.stringify(params, { arrayFormat: 'repeat' }),
    data: { data: body },
    params: null,
    headers: { 'Content-Type': 'multipart/form-data' },
    onUploadProgress: (progressEvent: AxiosProgressEvent) => {
      onUploadProgress(progressEvent)
    }
  })
    .then((resp) => {
      return {
        status: resp.data.status,
        payload: resp.data.payload,
        response: resp
      }
    })
    .catch((err) => {
      showError('上传失败，请检查网络后重试，或联系系统管理员！')
      console.log(err)
      throw new Error(err)
    })
}

// download 函数部分

function _download(res: AxiosResponse, fileName: string) {
  const content = res.data
  // 构造一个blob对象来处理数据
  const blob = new Blob([content])

  // 对于<a>标签，只有 Firefox 和 Chrome（内核） 支持 download 属性
  // IE10以上支持blob但是依然不支持download
  if ('download' in document.createElement('a')) {
    // 支持a标签download的浏览器
    const link = document.createElement('a') // 创建a标签
    link.download = fileName // a 标签添加属性
    link.style.display = 'none'
    link.href = URL.createObjectURL(blob)
    document.body.appendChild(link)
    link.click() // 执行下载
    URL.revokeObjectURL(link.href) // 释放url
    document.body.removeChild(link) // 释放标签
  } else {
    throw new Error('设备浏览器不支持下载')
  }
}
